import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.zest.core.widgets.Graph;
import org.eclipse.zest.core.widgets.GraphItem;
import org.eclipse.zest.core.widgets.GraphNode;

/**
 * 
 * Static container class for UI item listeners
 *
 */
public class BaphiListeners {
	
	private static Display d;
	private static Shell shell;
	private static Graph g;
	private static BaphiDialogs bd;
	private static NodeUtils nu;
	private static BaphiFileHandler bfh;

	/**
	 * Set up UI item listeners. More nasty helper/utility functions passed in.
	 * @param d
	 * @param shell
	 * @param g
	 * @param bd
	 * @param nu
	 * @param bfh
	 */
	public BaphiListeners(Display d, Shell shell, Graph g, BaphiDialogs bd, NodeUtils nu, BaphiFileHandler bfh)
	{
		BaphiListeners.d = d;
		BaphiListeners.shell = shell;
		BaphiListeners.g = g;
		BaphiListeners.bd = bd;
		BaphiListeners.nu = nu;
		BaphiListeners.bfh = bfh;
	}
	
	/**
	 * 
	 * Listener for menu item that creates a new GraphNode
	 *
	 */
	public static class PopupNewNode implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
		}

		public void widgetSelected(SelectionEvent e) {
			GraphNode newNode = nu.createNode("NewNode", d.getCursorLocation().x, d.getCursorLocation().y, NodeColorUtils.NodeColor.Violet);
			GraphItem gi[] = { newNode };
			g.setSelection(gi); // Select the new node
			bd.nodeNameDialog("Name New Node");
		}
	};

	/**
	 * 
	 * Listener for menu item that renames the selected GraphNode(s)
	 *
	 */
	public static class PopupRenameNode implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
		}

		@SuppressWarnings("unchecked")
		public void widgetSelected(SelectionEvent e) {
			List<GraphItem> selection = g.getSelection();
			
			if (!selection.isEmpty())
				bd.nodeNameDialog("Rename Node");
		}
	};
	
	/**
	 * 
	 * Listener for menu item that deleted the selected GraphItem(s)
	 *
	 */
	public static class PopupDeleteNode implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
		}

		@SuppressWarnings("unchecked")
		public void widgetSelected(SelectionEvent e) {

			nu.deleteNodes((List<GraphItem>) g.getSelection());
		}
	};
	
	/**
	 * 
	 * Listener for menu item that deletes everything, giving us an empty Graph.
	 *
	 */
	public static class NewMap implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
		}

		@SuppressWarnings("unchecked")
		public void widgetSelected(SelectionEvent e) {
			
			g.selectAll();
			nu.deleteNodes((List<GraphItem>) g.getSelection());
		}
	};
	
	/**
	 * 
	 * Listener for menu item that prompts for a filename, erases everything, and reads in new Graph data from a file
	 *
	 */
	public static class Open implements SelectionListener {
		
		public void widgetDefaultSelected(SelectionEvent e) {
		}

		@SuppressWarnings("unchecked")
		public void widgetSelected(SelectionEvent e) {
			FileDialog fd = new FileDialog(shell, SWT.OPEN);
            fd.setText("Open Map File");
            fd.setFilterPath("C:/");
            String[] filterExt = { "*.bmf", "*.*" };
            fd.setFilterExtensions(filterExt);
            String[] filterName = { "Baphi Map File (*.bmf)", "*.*" };
            fd.setFilterNames(filterName);
            String selected = fd.open();
            if (selected != null)
            {
    			g.selectAll();
    			nu.deleteNodes((List<GraphItem>) g.getSelection());
            	bfh.readBaphiGraph(selected);
            }
	    }
	};
	
	/**
	 * 
	 * Listener for menu item that prompts for a filename and writes the Graph data out to that file
	 *
	 */
	public static class Save implements SelectionListener {
		
		public void widgetDefaultSelected(SelectionEvent e) {
		}

		public void widgetSelected(SelectionEvent e) {
			FileDialog fd = new FileDialog(shell, SWT.SAVE);
            fd.setText("Save Map File");
            fd.setFilterPath("C:/");
            String[] filterExt = { "*.bmf" , "*.*" };
            fd.setFilterExtensions(filterExt);
            String[] filterName = { "Baphi Map File (*.bmf)", "*.*" };
            fd.setFilterNames(filterName);
            fd.setOverwrite(true);
            String selected = fd.open();
            if (selected != null)
            	bfh.writeBaphiGraph(selected);
	    }
	};

	/**
	 * 
	 * Listener for menu item that exits the application.
	 *
	 */
	public static class ExitApp implements SelectionListener {
		
		public void widgetDefaultSelected(SelectionEvent e) {
		}

		public void widgetSelected(SelectionEvent e) {
			// TODO If map is 'dirty' (needs saving), prompt user to save, cancel, or exit anyway
			// TODO If map is 'clean' (matches saved map), just exit
			// TODO Implement exit(); 
	    }
	};

	/**
	 * 
	 * Listener for menu item that selects all GraphItems
	 *
	 */
	public static class SelectAll implements SelectionListener {

		public void widgetDefaultSelected(SelectionEvent e) {
		}

		public void widgetSelected(SelectionEvent e) {
			g.selectAll();
		}
	};
	
	/**
	 * 
	 * Listener for menu item that changes a GraphNode's color
	 *
	 */
	public static class ColorMenuItem implements SelectionListener {
		
		public void widgetDefaultSelected(SelectionEvent e) {
			
		}

		@SuppressWarnings("unchecked")
		public void widgetSelected(SelectionEvent e) {
			for (GraphItem gi : (List<GraphItem>) g.getSelection())
			{
				if (gi.getItemType() == GraphItem.NODE)
				{
					GraphNode gn = (GraphNode) gi;
					NodeColorUtils.NodeColor nodeColor = (NodeColorUtils.NodeColor) e.widget.getData();
					gn.setData(nodeColor);
					gn.setImage(nu.getImage(nodeColor.getIdx()));
				}
			}
		}
	}
	
	/**
	 * 
	 * Listener that looks at mouse clicks and saves the current list of selected nodes
	 *
	 */
	public static class GraphMouseListener implements MouseListener {
		
		@SuppressWarnings("unchecked")
		public void mouseDown(MouseEvent e) {
			
			List<GraphItem> newSelection = g.getSelection();
			
			if (e.button == 1)
			{
				switch (e.stateMask)
				{
				case SWT.NONE:
					nu.saveSelection(newSelection);
					break;
				case SWT.CTRL:
					nu.saveSelection(newSelection);
					break;
				case SWT.SHIFT:
					// Shift-Click to create a connection between the previously-selected nodes and the current selection
					nu.makeConnection();
					break;
				}
			}
		}

		public void mouseUp(MouseEvent e) {
    	  
		}

		@SuppressWarnings("unchecked")
		public void mouseDoubleClick(MouseEvent e) {
			List<GraphItem> selection = g.getSelection();
			
			// Double-click a node to rename it.
			if (!selection.isEmpty())
				bd.nodeNameDialog("Rename Node");
		}
    }; 
}
